/**
 * axios封装;
 */
//安装axios和qs（npm install axios或者yarn add axios）(npm install qs)
import axios from "axios";
import qs from "qs";
import { ElMessage } from "element-plus";
import store from "@/store";
import router from "../../../router";
import { local, session } from "@/utils/local";
import { _login } from "@/api/login";
import { loginout } from "@/utils/outLogin";

// 创建axios实例
const instance = axios.create({
  baseURL: import.meta.env.VITE_BASE_URL, // 设置基础URL
  headers: {
    "Content-Type": "application/json;charset=utf-8",
  },
  timeout: 1000 * 60 * 10, // 设置请求超时时间
});
// 创建一个空对象，用于存储每个请求的标识符和取消函数。
let pending: any = {};
const CancelToken = axios.CancelToken;
// 取消重复请求
function removePending(key: any, isRequest = false) {
  if (pending[key] && isRequest) pending[key]("取消重复请求");
  delete pending[key];
}

// 请求拦截器
instance.interceptors.request.use(
  (config: any) => {
    let { url, method, headers, responseType, showName } = config;
    const tokenObj = store.getters?.tokenObj;
    // 设置接口白名单（不需要token的接口）
    // 当前请求的接口名称
    const currentUrl = url.slice(0, url.indexOf("?"));
    // 白名单接口名称数组
    const whiteList = [] as any;
    // 登录白名单
    const loginList = [
      "/oauth/token",
      "/front/public/captcha/getCaptcha",
    ] as any;
    if (!whiteList?.includes(currentUrl)) {
      if (tokenObj?.token || !loginList.includes(url)) {
        let expiration = isDateAfterExpiration(
          new Date(tokenObj?.tokenExpirationTime),
          new Date(),
          tokenObj?.expiresIn
        );
        if (expiration) {
          ElMessage.warning("登录信息已过期，请重新登录！");
          return loginout();
        }
        headers.Authorization = `${tokenObj.tokenHead}${tokenObj.token}`;
      } else {
        headers.Authorization = "Basic Y3VybF9jbGllbnQ6c2VjcmV0";
      }
    }
    headers["Content-Type"] = "application/json;charset=UTF-8";
    responseType ? (headers.responseType = responseType) : "";
    // 设置公司id
    const userCompany = store.getters.userCompany;
    const key = `${url}&${method}`;
    removePending(key);
    config.cancelToken = new CancelToken((c) => {
      pending[key] = c;
    });
    return config;
  },
  (error) => {
    // 对请求错误做些什么
    Promise.reject(error);
  }
);

// 响应拦截器
instance.interceptors.response.use(
  (response: any) => {
    // 对响应数据做点什么，例如处理状态码等
    const { data, config, headers, request, status } = response;
    const key = `${config?.url}&${config?.method}`;
    removePending(key);
    // console.log(response);
    if (status === 200) {
      if (!data?.code) return Promise.resolve(data);
      switch (data?.code) {
        case 10000:
          return Promise.resolve(data);
          break;
        case -10000:
          return Promise.resolve(data);
          break;
        case -10002:
          resetToken();
          break;
        case -10006:
          return Promise.resolve(data);
          break;
        case -10009:
          return Promise.resolve(data);
          break;
        case -50000:
          ElMessage.error(data?.message ?? "服务器未知错误,请稍后再试...");
          break;
        case -60000:
          ElMessage.error(data?.message ?? "服务器未知错误,请稍后再试...");
          setTimeout(() => {
            return router.push("/viwe401");
          }, 1000);
        default:
          ElMessage.warning(data?.message || "获取数据失败");
          break;
      }
      return response.data;
    } else {
      return Promise.reject(new Error("请求失败"));
    }
  },
  (error) => {
    // 对响应错误做点什么
    return Promise.reject(error);
  }
);
// 刷新token
async function resetToken() {
  const tokenObj = store.getters.tokenObj;
  let res: any = await _login({
    grantType: "refresh_token",
    refreshToken: tokenObj?.refreshToken || "",
  });
  if (res) {
    const tokenObj = store.getters?.tokenObj;
    // 更新过期时间
    tokenObj.tokenExpirationTime = new Date();
    tokenObj.expiresIn = res?.expiresIn ?? 43200;
    store.commit("user/setTokenObj", tokenObj);
  } else {
    loginout();
  }
}
/**
 * token令牌管理模块
 *
 * @param initialT token设定时间
 * @param newT 当前时间
 * @param expirationT 超时时间（默认12小时）
 * @return  token是否满足超时时间
 * @throws  输入有误，返回false
 */
function isDateAfterExpiration(
  initialT: any,
  newT: any,
  expirationT: number = 12
) {
  // 检查传入的Date对象是否有效
  if (
    !initialT ||
    !newT ||
    isNaN(initialT.getTime()) ||
    isNaN(newT.getTime())
  ) {
    return false;
  }

  // 计算时间差（毫秒）
  const timeInitial = initialT.getTime();
  const timeNew = newT.getTime();
  const difference = timeNew - timeInitial;

  // 将过期时间转换为毫秒
  const expirationInMs = expirationT * 1000;

  // 判断新时间是否在初始时间之后指定的小时数
  return difference >= expirationInMs;
}

const http = {
  post(url: string, data?: any, headers = {}) {
    return instance({
      method: "post",
      url: url,
      data: data,
      headers,
    });
  },
  // 文件流请求
  postbolb(url: string, data?: any, headers?: any) {
    return instance({
      method: "post",
      url: url,
      data: data,
      headers: {
        ...headers,
        responseType: "blob",
      },
      responseType: "blob",
    });
  },
  get(url: string, data?: any, headers = {}) {
    return instance({
      method: "get",
      url: url,
      data: data,
      headers,
    });
  },
  put(url: string, data?: any) {
    return instance({
      method: "put",
      url: url,
      data: data,
    });
  },
  delete(url: string, data?: any) {
    return instance({
      method: "delete",
      url: url,
      data: data,
    });
  },
};
export default http;
